﻿using System;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNet.SignalR.Client.Http;
using Microsoft.AspNet.SignalR.Client.Transports;
using Sanelib.Core;

namespace NSBus.Server.PushNotification
{
    public class SignalRService : ISignalRService
    {
        private HubConnection _connection;
        private IHubProxy _serviceMessageProxy;
        private readonly string _signalREndPoint;
        private string _cid = string.Empty;
        public SignalRService()
        {
            _signalREndPoint = ConfigurationManager.AppSettings["SignalRServerUri"];
        }

        private HubConnection GetHubConnection()
        {
            if (_connection != null) return _connection;
            _connection = new HubConnection(_signalREndPoint) {CookieContainer = new CookieContainer()};
          //  _connection.CookieContainer.Add(GetAuthCookie());
            _connection.ConnectionSlow += OnConnectionLost;
            _connection.Error += OnSignalRError;
            return _connection;
        }

        void OnSignalRError(Exception obj)
        {
            Debugger.Break();

        }

        void OnConnectionLost()
        {
            Debugger.Break();
        }

        private IHubProxy GetServiceChatHubProxy()
        {
            if (_serviceMessageProxy != null) return _serviceMessageProxy;
            try
            {
                var hubConnection = GetHubConnection();
                _serviceMessageProxy = hubConnection.CreateHubProxy("ServiceChatHub");
                _serviceMessageProxy.On<string>("showMessage", Console.WriteLine);
                
                IClientTransport transport = new ServerSentEventsTransport(new DefaultHttpClient());
                hubConnection.Start(transport).Wait();
                _cid = _connection.ConnectionId;
                Logger.Log(LogType.Info, this, "SignalR with cid: " + _cid);
            }
            catch (Exception exception)
            {
                Logger.Log(LogType.Error, this, "Broadcast Message", exception);
            }
            
            return _serviceMessageProxy;
        }

        public void SendMessage(string message, string who)
        {
            var hub = GetServiceChatHubProxy();
            if (hub == null) return;
            if (who == null) _serviceMessageProxy.Invoke("sendAll", message);
            else _serviceMessageProxy.Invoke("sendPrivate", message, who);
        }

        private Cookie GetAuthCookie()
        {
            var bytes = new UTF8Encoding().GetBytes("{\"username\":\"admin\",\"password\":\"admin\"}");
            var req = (HttpWebRequest)WebRequest.Create(_signalREndPoint + "/api/auth");
            req.ContentType = "application/json; charset=utf-8";
            req.ContentLength = bytes.Length;
            req.Accept = "application/json";
            req.Method = "POST";
            var stm = req.GetRequestStream();
            stm.Write(bytes, 0, bytes.Length);
            stm.Close();
            var resp = (HttpWebResponse) req.GetResponse();
            FixCookies(req, resp);
            var cook = resp.Cookies[0];
            var rStm = resp.GetResponseStream();
            if (rStm == null) throw new Exception("Response stream is null");
            var stmr = new StreamReader(rStm);
            var response = stmr.ReadToEnd();
            Logger.Log(LogType.Info, this, response);
            return cook;
        }

        private static void FixCookies(HttpWebRequest request, HttpWebResponse response)
        {
            for (var i = 0; i < response.Headers.Count; i++)
            {
                var name = response.Headers.GetKey(i);
                if (name != "Set-Cookie") continue;
                var value = response.Headers.Get(i);
                foreach (var singleCookie in value.Split(','))
                {
                    var match = Regex.Match(singleCookie, "(.+?)=(.+?);");
                    if (match.Captures.Count == 0) continue;
                    response.Cookies.Add(
                        new Cookie(
                            match.Groups[1].ToString(),
                            match.Groups[2].ToString(),
                            "/",
                            request.Host.Split(':')[0]));
                }
            }
        }
    }
}